
#include <gomoku/core/Core.h>
#include <gomoku/core/Gomoku.h>

// modules impl
#include <gomoku/AI/DefaultPlayer.h>
#include <gomoku/gui/DefaultGui.h>
#include <gomoku/referee/DefaultReferee.h>
// states impl
#include <gomoku/core/TitleScreen.h>

namespace gomoku
{
    Core::Core()
        : _referee(0), _gui(0), _black(0), _white(0), _states()
    {
        _referee = new gomoku::DefaultReferee;
        _gui = new gomoku::DefaultGui;
        _black = new gomoku::DefaultPlayer;
        _white = new gomoku::DefaultPlayer;

        _referee->connectGui(_gui);
        _referee->connectBlack(_black);
        _referee->connectWhite(_white);

        _gui->connectReferee(_referee);
        _white->connectReferee(_referee);
        _black->connectReferee(_referee);

        _black->setColor(BLACK);
        _white->setColor(WHITE);

        _states.setContext(Context(_gui, _black, _white, _referee));
    }

    Core::~Core()
    {
        delete _black;
        delete _white;
        delete _gui;
        delete _referee;
    }

    void Core::init()
    {
        _states.registerState<TitleScreen>(TITLE_SCREEN);
        _states.pushState(TITLE_SCREEN);
    }

    void Core::run()
    {
        float dt(1.0 / 30.0);
        float elapsedTime(0.0);

        init();
        while(!_states.isEmpty())
        {
            elapsedTime += _gui->restartClock();
            while (elapsedTime > dt)
            {
                elapsedTime -= dt;
                pollEvent();
                update(dt);
            }
            render();
        }
    }

    void Core::pollEvent()
    {
        _states.handleEvent();
    }
    
    void Core::update(float dt)
    {
        _states.update(dt);
    }

    void Core::render()
    {
        _states.draw();
    }
}
